import os
import json
import yaml
import threading
import time  # 可能前面的import模块对time有影响,故放在最后
from datetime import datetime, timedelta
from tq_py.strategy import Strategy
from tq_py.config import Config
from multiprocessing import Process,Pool,Pipe,Queue,Manager
import os
import threading
import pickle
from tqsdk import TqApi, TqAuth, TargetPosTask,TqKq
import threading
class TTP(object):

    def __init__(self):

        self.cfg = Config()
        self.process_list=[]
        self.stra_instances = []
        #self.pool = Pool(4)
        self.threads=[]


    def splitfilename(self,filename):
        res=filename.split('_')
        if len(res)==2:
            [classname,setion_name]=res
        if len(res)==1:
            classname = res[0]
            setion_name=res[0]
        return classname


    def load_strategy(self):
        """加载../strategy目录下的策略"""

        if not self.cfg.stra_path:
            return
        for path in self.cfg.stra_path:

            for stra_name in self.cfg.stra_path[path]:
                classname=self.splitfilename(stra_name)
                f = os.path.join(path, '{}.py'.format(classname))
                # 只处理对应的 py文件
                if os.path.isdir(f) or os.path.splitext(f)[0] == '__init__':
                    continue
                # 以目录结构作为 namespace
                module_name = "{0}.{1}".format(os.path.split(os.path.dirname(f))[1], classname)

                module = __import__(module_name)  # import module

                c = getattr(getattr(module, classname), classname)  # 双层调用才是class,单层是为module

                if not issubclass(c, Strategy):  # 类c是Strategy的子类
                    continue

                # 与策略文件同名的 yaml 作为配置文件处理
                cfg_name = os.path.join(path, '{0}.yml'.format(stra_name))

                cfg_name='.//'+cfg_name


                if os.path.exists(cfg_name):
                    with open(cfg_name, encoding='utf-8') as stra_cfg_json_file:
                        params = yaml.load(stra_cfg_json_file,Loader=yaml.FullLoader)
                        if params['Params']['ID'] not in self.cfg.stra_path[path][stra_name]:
                            continue
                        stra: Strategy = c(cfg_name)

                        # self.cfg.log.info("# strategy:{0}".format(stra))
                        self.stra_instances.append(stra)
                else:
                    self.cfg.log.error("缺少对应的json文件{0}".format(cfg_name))


    def Run(self):
        self.load_strategy()
        print('Main:', os.getpid())
        for cta in self.stra_instances:
            t = threading.Thread(target=cta.stra, args=())  # 循环 实例化2个Thread类，传递函数及其参数，并将线程对象放入一个列表中
            t.start()
            self.threads.append(t)
            #print(self.get_pickling_errors(cta))
            #p = Process(target=cta.stra)
            #p.start()
            #self.process_list.append(p)

            #self.pool.apply_async(func=cta.stra, args=())  # func子进程执行完后，才会执行callback，否则callback不执行（而且callback是由父进程来执行了）
            # pool.apply(func=Foo, args=(i,))



    def get_pickling_errors(self,obj, seen=None):
        if seen == None:
            seen = []
        try:
            state = obj.__getstate__()
        except AttributeError:
            return
        if state == None:
            return
        if isinstance(state, tuple):
            if not isinstance(state[0], dict):
                state = state[1]
            else:
                state = state[0].update(state[1])
        result = {}
        for i in state:
            try:
                pickle.dumps(state[i], protocol=2)
            except:
                if not state[i] in seen:
                    seen.append(state[i])
                    result[i] = self.get_pickling_errors(state[i], seen)
        return result